package com.mrwang.example.nio.part20191027;

import net.jpountz.util.ByteBufferUtils;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

public class NioTest2 {

    public static void main(String[] args) {
        int[] ports = new int[5];
        ports[0] = 5000;
        ports[1] = 5001;
        ports[2] = 5002;
        ports[3] = 5003;
        ports[4] = 5004;
        try {
            /**
             * 事件收集器，存储就绪的事件，这个组件的目的是为了解决传统的 socket io 读写需要多线程的情况（selector避免了开启多个线程），
             * 通过一个选择器使用单线程实现了对多个网络连接的管理
             */
            Selector selector = Selector.open();
            //开启5个端口
            for (int port : ports
            ) {

                ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
                serverSocketChannel.configureBlocking(false);
                ServerSocket socket = serverSocketChannel.socket();
                InetSocketAddress inetSocketAddress = new InetSocketAddress(port);
                socket.bind(inetSocketAddress);
                serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
                System.out.println("监听端口： " + port);
            }
            while (true) {
                int numbers = selector.select();
                System.out.println("numbers:" + numbers);
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                System.out.println("selectionKeys:" + selectionKeys);
                Iterator<SelectionKey> iterator = selectionKeys.iterator();
                while (iterator.hasNext()) {
                    SelectionKey selectionKey = iterator.next();

                    if (selectionKey.isAcceptable()) {
                        System.out.println("selectionKey.channel()=="+selectionKey.channel());
                        ServerSocketChannel serverSocketChannel = (ServerSocketChannel) selectionKey.channel();
                        SocketChannel socketChannel = serverSocketChannel.accept();
                        socketChannel.configureBlocking(false);
                        socketChannel.register(selector, SelectionKey.OP_READ);
                        iterator.remove();
                        System.out.println("获取客户端连接：" + serverSocketChannel);
                    } else if (selectionKey.isReadable()) {
                        SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
                        int bytesRead = 0;
                        while (true) {
                            ByteBuffer bb = ByteBuffer.allocate(512);
                            bb.clear();
                            int read = socketChannel.read(bb);
                            if (read <= 0) {
                                break;
                            }
                            bb.flip();
                            socketChannel.write(bb);
                            bytesRead += read;
                            System.out.println("读取：" + bytesRead + "，来源于：" + socketChannel);
                            iterator.remove();
                        }
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
